/* 
 * Copyright 2011 Steffen Schäfer
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.richsource.gwtplug.client;

import java.util.HashMap;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;

/**
 * Abstract implementation for component exporters used to create a
 * {@link JavaScriptObject} with registered native functions that delegate to
 * the exported component.
 * 
 * @author Steffen Schäfer
 * 
 */
public abstract class PluginComponentExporter {

	public PluginComponentExporter() {
	}

	public JavaScriptObject createFor(Object component) {
		JavaScriptObject exporter;
		if (GWT.isProdMode()) {
			exporter = createForProd(getType(), component);
		} else {
			exporter = createForDev(getType(), component);
		}
		createMethods(exporter);
		return exporter;
	}

	private static HashMap<Integer, Object> componentMap = new HashMap<Integer, Object>();
	private static int nextIdx = 0;

	protected abstract void createMethods(JavaScriptObject exporter);

	protected abstract String getType();

	private JavaScriptObject createForDev(String type, Object component) {
		int idx = nextIdx++;
		componentMap.put(idx, component);
		return innerCreateForDev(type, idx);
	}

	private final native JavaScriptObject innerCreateForDev(String type, int idx) /*-{
		var componentExporter = new Object();
		componentExporter.type = type;
		componentExporter.idx = idx;
		return componentExporter;
	}-*/;

	private static Object getComponentForExporter(JavaScriptObject exporter) {
		if (GWT.isProdMode()) {
			return getComponent(exporter);
		} else {
			return componentMap.get(getIdx(exporter));
		}
	}

	private static native JavaScriptObject getComponent(
			JavaScriptObject exporter) /*-{
		return exporter.component;
	}-*/;

	private static native int getIdx(JavaScriptObject exporter) /*-{
		return exporter.idx;
	}-*/;

	private final native JavaScriptObject createForProd(String type,
			Object component) /*-{
		var componentExporter = new Object();
		componentExporter.type = type;
		componentExporter.component = component;
		return componentExporter;
	}-*/;

}
